<template>
  <div class="widget-tree-container">
    <el-tree
      ref="widgetPickerTree"
      node-key="id"
      :lazy="true"
      :load="loadNode"
      :props="{label: 'name', isLeaf: judgeLeafNode}"
      :expand-on-click-node="false"
      :auto-expand-parent="false"
      :highlight-current="true"
      :accordion="false"
      :default-expanded-keys="expandedKey"
      @node-expand="nodeExpand"
      @node-collapse="nodeCollapse">
      <div
        slot-scope="{data}"
        v-if="!data.isDeleted"
        :id="`pickerTreeNode-${data.id}`"
        :class="nodeClass(data)"
        class="custom-tree-node"
        @click="nodeClick(data)"
        @dblclick="selectWidget(data)">
	      <span class="custom-tree-name">{{data.name}}</span>
        <div class="flex-justify-end">
          <i :class="!data.displayForPicker ? 'icon-Notvisible' : 'icon-browse'"
             class="iconfont font-size-20"
             @click.stop="widgetDisplayCtrl(data)"></i>
        </div>
      </div>
      <div slot-scope="{data}" v-else class="custom-tree-node custom-tree-node-disabled">
        <span>{{data.name}}（已删除）</span>
      </div>
    </el-tree>
  </div>
</template>

<script>
  import {PageHandler} from "@/modules/IDE/pageHandler";
  import {WidgetFactory} from "@/modules/IDE/widgetFactory";
  import {mapActions, mapState} from "vuex";

  export default {
    name: 'WidgetPickerTree',
    props: {
      pageHdl: {
        type: PageHandler,
        default: () => {
          return undefined;
        }
      },
	    editorType: {
		    type: String,
		    default: 'room', // room/component
	    },
    },
    data() {
      return {
	      treeRef: null,
	      treeData: [],
	      expandedKey: [],
	      rootNode: null, // 用于主动 loadNode
	      treeLoadResolve: null,
      };
    },
	  computed: {
		  ...mapState({
			  curPageTypeForPicker: state => state.ide.curPageTypeForPicker,
			  widgetPickerInfo: state => state.ide.widgetPickerInfo,
		  }),
		  nodeClass() {
			  return (widget = {}) => {
				  const {id, isRoot, activeForPicker} = widget;
				  if (activeForPicker) {
					  return ['font-weight-bold', 'font-color-primary'];
				  }
				  // 以下逻辑对 active 的 组件所属的 page 节点进行字体加粗
				  if (!isRoot) return false;
				  if (this.editorType === 'component') {
					  return ['font-weight-bold', 'font-gray-10'];
				  }
				  const {type, activePageForPicker = {}} = this.pageHdl;
				  if (this.curPageTypeForPicker === type && activePageForPicker.id === id) {
					  return ['font-weight-bold', 'font-gray-10'];
				  }
			  }
		  },
	  },
	  watch: {
		  'widgetPickerInfo.show': {
			  handler(show) {
				  if (!show) return;
				  const {selectWidgetId = ''} = this.widgetPickerInfo;
				  if (!selectWidgetId) return;
				  const widget = WidgetFactory.getWidgetById(selectWidgetId);
				  if (!widget) return;
				  this.collapseAllNode();
				  this.autoExpandNode(widget);
			  },
			  immediate: true
		  }
	  },
	  mounted() {
		  this.treeRef = this.$refs['widgetPickerTree'];
		  this.$EventBus.$on('selectWidgetForPicker', (widget) => {
			  // 判断当前选中的组件是否属于 pageHdl，防止事件通知执行多次
			  const {contain} = this.pageHdl.judgePageContainWidget(widget);
			  if (!contain) return;
			  // 如果当前选中的组件节点的子级已经被展开过，则点击节点时，不要将子节点折叠
			  // 通过 exceptCollapse 传入 collapseAllNode 方法
			  const exceptCollapse = [];
			  this.expandedKey.forEach(widgetId => {
				  const fullPath = WidgetFactory.getWidgetFullPath(widgetId);
				  if (fullPath.includes(widget.id)) {
					  exceptCollapse.push(widgetId);
				  }
			  });
			  this.collapseAllNode(exceptCollapse);
			  this.autoExpandNode(widget);
		  });
		  this.$EventBus.$on('dbClickWidgetForPicker', (widget = {}) => {
			  const {relateSubPage, relateSubPageId} = widget;
			  if (relateSubPage) {
				  const nodeId = `pickerTreeNode-${relateSubPageId}`;
				  const element = document.getElementById(nodeId);
				  element && element.scrollIntoView({block: 'center', behavior: 'smooth'});
			  }
		  });
	  },
	  beforeDestroy() {
		  this.$EventBus.$off('selectWidgetForPicker');
		  this.$EventBus.$off('dbClickWidgetForPicker');
	  },
	  methods: {
	    loadNode(node, resolve) {
		    const {level = 0, data = {}} = node;
				// 过滤 isDeleted 节点
				if (level === 0) {
					this.rootNode = node;
					this.treeLoadResolve = resolve;
					resolve(this.pageHdl.pages.filter(widget => !widget.isDeleted));
				} else {
					resolve(data.children.filter(widget => !widget.isDeleted));
				}
	    },
	    // 自动展开选中 widget 的父节点
	    autoExpandNode(widget = {}) {
		    const {parentId = ''} = widget;
				if (!parentId) return;
				const parent = WidgetFactory.getWidgetById(parentId);
				if (!parent) return;
				if (!this.expandedKey.includes(parentId)) {
					this.expandedKey.push(parentId);
				}
				this.autoExpandNode(parent);
	    },
		  collapseAllNode(exceptCollapse = []) {
			  this.expandedKey.forEach(widgetId => {
				  if (exceptCollapse.includes(widgetId)) return;
				  const node = this.treeRef.getNode(widgetId);
				  node && (node.expanded = false);
			  });
			  this.expandedKey = exceptCollapse;
		  },
		  nodeExpand(data) {
			  const widgetId = data.id;
			  if (this.expandedKey.includes(widgetId)) return;
			  this.expandedKey.push(widgetId);
		  },
		  nodeCollapse(data) {
			  const widgetId = data.id;
			  const idx = this.expandedKey.indexOf(widgetId);
			  !!~idx && this.expandedKey.splice(idx, 1);
		  },
	    // 判断是否为叶子节点
	    judgeLeafNode(data = {}) {
				const {children = [], relateSubPage = false, isDeleted = false} = data;
				return !children.length || relateSubPage || isDeleted;
	    },
      widgetDisplayCtrl(widget = {}) {
        widget.displayForPicker = !widget.displayForPicker;
      },
      nodeClick(widget = {}) {
        this.$emit('selectPage');
        this.$nextTick(() => {
          this.pageHdl.updateActivePage(widget, true);
          this.$EventBus.$emit('selectWidgetForPicker', widget);
        });
      },
	    selectWidget(widget = {}) {
		    !widget.relateSubPage && this.$emit('selectPage');
				this.$emit('selectWidget', widget);
	    }
    }
  };
</script>

<style scoped lang="less">

  .widget-tree-container {

    .custom-tree-node {
      display: flex;
      flex: 1;
      justify-content: space-between;
      align-items: center;
      height: 100%;
      padding-right: 10px;
      font-size: 14px;

	    .custom-tree-name {
		    display: inline-block;
		    max-width: 150px;
		    text-overflow: ellipsis;
		    overflow: hidden;
	    }
    }

    .custom-tree-node-disabled {
      cursor: not-allowed;
      text-decoration: line-through;
    }

    /deep/ .el-tree {
      border-radius: 4px;

      .el-tree-node__content {
        height: 35px !important;
        border-bottom: 1px solid @colorGray96;
      }
    }
  }

</style>
